﻿package wcl.net {
	import com.adobe.serialization.json.JSON;
	import com.adobe.xml.syndication.atom.PersonTag;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.system.Security;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import utils.ByteArrayHexDump;
	import wcl.Console;
	import wcl.json.JsonStr;
	
	/**
	 * ...
	 * @author ...
	 */
	public class JSONSocket extends Socket {
		
		public static var NAME:String = "JSONSocket";
		public static var DATA:String = NAME + "Data";
		public static var CONNECTED:String = NAME + "Connected";
		
		public var JSONStrSize:uint;
		public var JSONObjects:Array = new Array();
		
		public function JSONSocket() {
			super()
			addEventListener(Event.CLOSE, handleDC)
			addEventListener(Event.CONNECT, handleConnect);
			addEventListener(IOErrorEvent.IO_ERROR, handleIoError)
			addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecError)
			addEventListener(ProgressEvent.SOCKET_DATA, readJSON);
		}
		
		private function handleDC(e:Event):void {
			trace("Server Disconnected")
			close()
		}
		
		private function handleSecError(e:SecurityErrorEvent):void {
			trace(e.text)
		}
		
		private function handleIoError(e:IOErrorEvent):void {
			trace(e.toString());
		}
		
		public function initialize():void {
			JSONStrSize = 0;
			endian = Endian.LITTLE_ENDIAN;
			trace(Security.sandboxType)
			if (Security.sandboxType == "remote") {
				trace("Loading Policy File")
				//Security.loadPolicyFile("http://server.local/crossdomain.xml")
			}
			JSONObjects.slice();
			//Security.loadPolicyFile("crossdomain.xml")
			//addEventListener(Event.CONNECT, onConnect);
			
		}
		
		public function ConnToServer(host:String,post:int):void {
			trace("Connecting To Server")
			//connect("server.local", 56000)
			connect(host, post)
		}
		
		public function handleConnect(e:Event):void {
			trace("Connected to Server");
			removeEventListener(Event.CONNECT, handleConnect);
			dispatchEvent(new Event(JSONSocket.CONNECTED));
			
		}
		
		public function readJSON(e:ProgressEvent):void {
			trace("bytesLoaded:" + e.bytesLoaded);
			var s:String = '';
			while (bytesAvailable) {
				var b:int = readByte();
				s += ((b == 0)?'':String.fromCharCode(b));
			}
			flush();
			trace(bytesAvailable);
			trace(s);
			//readJSONSize();
		}
		
		
		
		public function readJSONSize():void {
			if (JSONStrSize == 0) {
				if (bytesAvailable >= 4) {
					JSONStrSize = 20;// readUnsignedInt()
					//trace("Json String Size: " + JSONStrSize)
					//trace("Json String Size: " + JSONStrSize)
					readJSONObject();
				}
			}else {
				//readJSONObject();
			}
		}
		
		public function readJSONObject():void {
			trace("Reading Json Object bytesAvail: " + bytesAvailable + " JSONStrSize: " + JSONStrSize)
			trace("Reading Json Object bytesAvail: " + bytesAvailable + " JSONStrSize: " + JSONStrSize)
			if (bytesAvailable >= JSONStrSize) {
				var bytes:ByteArray = new ByteArray()
				readBytes(bytes, 0, JSONStrSize)
				var JSONStr:String = bytes.readUTFBytes(bytesAvailable)
				trace("JSONStr: " + JSONStr)
				trace("JSONStr: " + JSONStr)
				JSONStrSize = 0;
				//JSONObjects.push(JSON.decode(JSONStr))
				if (JSONObjects.length > 0) {
					dispatchEvent(new Event(DATA));
				}
				// This if is redundant
				if (bytesAvailable >= 4) {
					readJSONSize();
				}
			}
		}
		public function writeJSONStr(cmd:uint, jsonStr:JsonStr):void {
			//writeUTFBytes(jsonStr.bytes.length + 2 + '');
			trace("-----------------------------------------------");
			writeByte(cmd);
			writeBytes(jsonStr.bytes);
			writeUTFBytes('\n');
			flush();
		}
		public function popJSON():Object {
			return JSONObjects.shift();
		}
	}
	
}